package core;/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-08-05 19:03
 * @notify
 * @version 1.0
 */

import annotation.Ignore;
import annotation.Test;
import annotation.TestCase;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RunTest {

    //测试文件
    private Class clazz;

    //成功
    private Map<Method, Long> succeed = new HashMap<Method, Long>();

    //失败
    private List<Method> failed = new ArrayList<Method>();

    //忽略
    private List<Method> ignore = new ArrayList<Method>();

    //失败

    /*接收一个Class文件*/
    public RunTest(Class clazz) {
        this.clazz = clazz;
    }

    /*
        接收一个classpath路径
    */
    public RunTest(String classPath) throws Exception {
        this(Class.forName(classPath));
    }

    public void run() {
        //判断是否使用了 @TestCase注解
        Annotation annotation = clazz.getAnnotation(TestCase.class);
        if (annotation == null) {
            throw new RuntimeException("您运行的不是一个测试方法,测试方法需要有 @TestCase");
        }

        //实例化该测试类
        Object obj;
        try {
            obj = clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("实例化类异常.");
        }

        //拿到测试类的所有方法
        Method[] methods = clazz.getMethods();

        for (Method method : methods) {
            //说明是个测试类
            if (method.getAnnotation(Test.class) != null) {
                //说明需要忽略不参与测试
                if (method.getAnnotation(Ignore.class) != null) {
                    //添加忽略
                    ignore.add(method);
                } else {
                    try {
                        //开始时间
                        Long start = System.currentTimeMillis();
                        method.invoke(obj, new Object[0]);
                        //结束时间
                        Long end = System.currentTimeMillis();
                        //添加成功
                        succeed.put(method, end - start);
                    } catch (Exception e) {
                        //添加失败
                        failed.add(method);
                    }

                }
            }
        }
        report();
    }

    //报告
    private void report() {
        StringBuilder sb = new StringBuilder();
        //成功个数
        int succeedLength = succeed.size();
        if (succeedLength != 0) {
            int succeedCount = 1;
            //成功次数
            sb = sb.append("本次运行:成功" + succeedLength + "个测试用例\n[");
            for (Map.Entry<Method, Long> entry : succeed.entrySet()) {
                sb.append(entry.getKey().getName() + "-->用时" + entry.getValue() + "毫秒");
                if (succeedCount < succeedLength) {
                    sb = sb.append(",");
                } else {
                    sb = sb.append("]");
                }
                ++succeedCount;
            }
        }

        //失败个数
        sb = concatString(failed, sb, "失败");

        //忽略个数
        sb = concatString(ignore, sb, "忽略");


        System.out.println(sb.toString());

    }

    private StringBuilder concatString(List<Method> list, StringBuilder sb, String str) {
        int size = list.size();
        if (size != 0) {
            sb = sb.append("\n本次运行:" + str + +size + "个测试用例\n[");
            for (int i = 0; i < size; i++) {
                sb = sb.append(list.get(i).getName());
                if (i < size - 1) {
                    sb = sb.append(",");
                } else {
                    sb = sb.append("]");
                }
            }
        }
        return sb;
    }
}
